브라우저 렌더링 과정을 알아보자
글 작성에 앞서
- 브라우저 렌더링과정을 예전에 찾아보았는데 최근에 프론트엔드에서 최적화하는 방법들을 찾아보다 오랜만에 궁금해서 다시 찾아보았다가 새롭게 알게된 사실들도 있었고 기억나지 않았던 내용들도 있어서 나중에 혼자 다시 볼 수 있도록 기록해보려고 한다. 오랜만에 관련 내용들을 찾아보아서 그런지 굉장히 재미있게 읽고 공부했다!
브라우저 렌더링(Browser Rendering)
- 보통 프론트엔드 면접에서 주소창에 도메인을 입력후 일어나는 일이 무엇인가?에 대한 질문들이 많이 나오는데 출발지점을 그쪽부터 가볍게 시작해보면서 작성해보려고 한다. 이유는 이번에 새롭게 알게된 사실들이 몇 가지 있어서 기억해두기 위해서..ㅎㅎ
-
우선 예를 들어 https://www.dltmdrbtjd.dev 를 입력했을때 일어나는 일은 우선 DNS 서버에 도메인 이름을 검색후 IP주소를 받아 오게 되었있다. 여기서 이번에 처음 알게된 사실은 도메인 이름을 OS 캐시에 저장해두고 캐싱되어 있으면 기존에 캐시에 저장해두었던 IP주소를 반환하고 없으면 그때 요청을 보내고 반환하도록 순서가 진행된다.
-
반환받은 IP주소를 사용해서 브라우저가 웹 서버에 해당하는 html 문서를 요청한다. 이때 IP주소가 없으면 찾을때까지 반복하는 과정이 이루어진다고 한다.
-
이번에 처음 알게된 내용인데 WAS(Web Application Server)와 DB에서 웹페이지 작업을 처리한다. 즉 이때 요청받은 웹 서버는 html,css image file 등을 처리하고 js,ts 등의 동적인 파일들은 이 WAS와 DB 사이에서 처리한다.
-
WAS에서 작업처리 결과를 웹 서버로 전송하고 웹 서버는 브라우저에게 html 문서 결과를 전달해준다. 이때 전달 과정에서 status code를 통해서 서버 요청에 따른 결과를 전달해준다.
- status code
- 1xx : 정보가 담긴 메시지
- 2xx : response 성공
- 3xx : 클라이언트를 다른 url로 리다이렉트
- 4xx : 클라이언트쪽의 에러
- 5xx : 서버쪽의 에러
- 브라우저의 렌더링 과정
- 이번에 처음 알게된 내용중 하나인데 웹 브라우저에 출력되는 단계를 CRP(Critical Rendering Path)라고 하고 6단계로 나뉘어진다.
- 성능 최적화를 위해서 수신받은 html, css, js 파일들이 어떤 단계에 걸쳐 일어나는지 파악후 해당 과정들을 최소화 하는게 좋다.
- DOM(Document Object Model) Tree 빌드
- Network 단계에서 통신을 통해 받아온 html은 byte형태로 전달되는데 이후 바이트 -> 문자 -> 토큰 -> 노드 -> 오브젝트 모델로 전환하는 과정을 수행한다. (렌더링 엔진이 html을 읽다가 script태그 또는 js코드를 컨텐츠로 담은 script태그를 만나면 DOM생성을 중단하고 js를 위한 과정이 이루어지는데 이는 맨 마지막쯤에 다루겠다.)
- CSSOM(CSS Object Model) Tree 빌드
- DOM 트리를 빌드했던것과 같이 html처럼 객체 모델로 전환하는것과 같은 작업이 CSS파일에도 적용된다.
- CSSOM 트리를 만들면서 특정 객체에 최종스타일을 지정할때 상위 객체의 스타일을 적용하는 방식으로 계산되는 스타일을 재귀적으로 세분화한다. 이 말에서 아직 재귀적으로 세분화한다는 부분에 대해서는 자세히 이해하지 못했다. 추후에 더 찾아보도록 해야겠다. 아마도 이 과정이 이루어지기 때문에 상위 객체에 지정한 스타일을 자식이 받아서 쓸수있는것 같다. 가령 예를 들자면 body에 font-size를 30px로 지정하면 모든 태그의 font-size가 30px인것처럼
- Render Tree 생성
- 앞서 만들어진 DOM과 CSSOM을 결합해서 렌더 트리를 생성한다. 렌더 트리는 렌더링에 필요한 노드만 선택해서 페이지를 렌더링하는데 사용된다.
- Layout
- 렌더 트리 노드들의 위치랑 크기를 계산하는 단계이고 페이지 상에 존재하는 객체의 크기를 렌더링 트리의 root부터 시작해서 모든 객체에 정확한 위치와 크기를 계산한다.
- Paint
- 계산된 값들을 기반으로 화면에 필요한 요소들을 실제로 그리는 작업을 실행한다. 레이아웃 단계에서 계산된 위치와 크기를 실제 px단위로 변환하여 화면에 출력해준다.
- Reflow & Repaint
- 이벤트가 발생하거나 했을때 html 요소,크기,위치를 변경해야 하는 경우가 있을때 발생하는 과정을 reflow라고 한다. 이 과정이 발생하면 렌더링 트리와 각 요소들의 크기,위치를 다시 계산하게된다. 또한 reflow에 따라 역시 다시 페인팅 해야하는 repaint도 발생한다.
- background-color, visibility와 같이 페인팅만 다시하는 경우는 독단적으로 수행한다.
- composition
- 레이아웃, 프린트 수행없이 레이어의 합성만 실행하는 단계이다. ex) Transform, opacity ...
- 이제 처음에 입력한 도메인주소에 맞는 화면이 출력된다!
-
앞서 DOM Tree 빌드 부분에 javaScript에 관한 부분을 조금 더 작성해보자면 렌더링 엔진이 html을 읽는중(파싱하며 DOM생성중)에 script태그나 javaScript 코드를 컨텐츠로 담은 script태그를 만나면 DOM 생성을 일시 중단후 script 태그의 src속성에 서버요청후 load한 js파일을 받는다. js파일이나 script내의 코드 파싱을 위해 JS엔진에 제어권을 이때 넘겨준다. JS엔진은 JS파일을 해석해 AST(추상 구문 트리)를 생성하고 AST를 기반으로 인터프리터가 실행할 수 있는 중간 코드인 byte코드를 생성후 실행한다. JS파싱과 실행이 끝나면 렌더링 엔진으로 다시 제어권을 넘겨주고 html 파싱이 멈춘 지점부터 다시 순차적으로 html을 파싱한다.
-
우선 기본적인 순서들과 각 렌더링 과정에 대해서 다시 정리해보았다. 사실 하나하나 자세히 들어가보면 그 내용과 지식들은 엄청나게 방대할 것 같다. 이러한 렌더링 과정과 각 순서에서 일어나는 일들을 숙지해두고 있는다면 추후에 성능최적화를 할때 도움이 되지 않을까해서 정리했는데 자료도 찾아보고 정리해보고 공부하는데 굉장히 재미있었던것 같다. 사실 js엔진이 돌아가는 순서와 원리도 굉장히 재미있었는데 이 부분은 나중에 기회가 되었을때 정리해보도록 해야겠다 !